#define USE_CUBE_MAP_SHADOW true
uniform sampler2D colorTexture;
uniform sampler2D depthTexture;
varying vec2 v_textureCoordinates;
uniform mat4 camera_projection_matrix;
uniform mat4 camera_view_matrix;
uniform samplerCube shadowMap_textureCube;
uniform mat4 shadowMap_matrix;
uniform vec4 shadowMap_lightPositionEC;
uniform vec4 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness;
uniform vec4 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth;
uniform float helsing_viewDistance;
uniform int helsing_textureType;
uniform sampler2D helsing_texture;
uniform float helsing_alpha;
uniform vec4 helsing_visibleAreaColor;
uniform vec4 helsing_invisibleAreaColor;
struct zx_shadowParameters
{
    vec3 texCoords;
    float depthBias;
    float depth;
    float nDotL;
    vec2 texelStepSize;
    float normalShadingSmooth;
    float darkness;
};
float czm_shadowVisibility(samplerCube shadowMap, zx_shadowParameters shadowParameters)
{
    float depthBias = shadowParameters.depthBias;
    float depth = shadowParameters.depth;
    float nDotL = shadowParameters.nDotL;
    float normalShadingSmooth = shadowParameters.normalShadingSmooth;
    float darkness = shadowParameters.darkness;
    vec3 uvw = shadowParameters.texCoords;
    depth -= depthBias;
    float visibility = czm_shadowDepthCompare(shadowMap, uvw, depth);
    return czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);
}
vec4 getPositionEC(){
    return czm_windowToEyeCoordinates(gl_FragCoord);
}
vec3 getNormalEC(){
    return vec3(1.);
}
vec4 toEye(in vec2 uv, in float depth){
    vec2 xy=vec2((uv.x*2.-1.), (uv.y*2.-1.));
    vec4 posInCamera=czm_inverseProjection*vec4(xy, depth, 1.);
    posInCamera=posInCamera/posInCamera.w;
    return posInCamera;
}
vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point){
    vec3 v01=point-planeOrigin;
    float d=dot(planeNormal, v01);
    return (point-planeNormal*d);
}
float getDepth(in vec4 depth){
    float z_window=czm_unpackDepth(depth);
    z_window=czm_reverseLogDepth(z_window);
    float n_range=czm_depthRange.near;
    float f_range=czm_depthRange.far;
    return (2.*z_window-n_range-f_range)/(f_range-n_range);
}
float shadow(in vec4 positionEC){
    vec3 normalEC=getNormalEC();
    zx_shadowParameters shadowParameters;
    shadowParameters.texelStepSize=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.xy;
    shadowParameters.depthBias=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.z;
    shadowParameters.normalShadingSmooth=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.w;
    shadowParameters.darkness=shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.w;
    vec3 directionEC=positionEC.xyz-shadowMap_lightPositionEC.xyz;
    float distance=length(directionEC);
    directionEC=normalize(directionEC);
    float radius=shadowMap_lightPositionEC.w;
    if (distance>radius)
    {
        return 2.0;
    }
    vec3 directionWC=czm_inverseViewRotation*directionEC;
    shadowParameters.depth=distance/radius-0.0003;
    shadowParameters.nDotL=clamp(dot(normalEC, -directionEC), 0., 1.);
    shadowParameters.texCoords=directionWC;
    float visibility=czm_shadowVisibility(shadowMap_textureCube, shadowParameters);
    return visibility;
}
bool visible(in vec4 result)
{
    result.x/=result.w;
    result.y/=result.w;
    result.z/=result.w;
    return result.x>=-1.&&result.x<=1.
    &&result.y>=-1.&&result.y<=1.
    &&result.z>=-1.&&result.z<=1.;
}

vec4 toReal(in vec2 clipPosition){
    //    vec4 wordPos = czm_inverseView * posInCamera;
    //    vec4 vcPos = camera_view_matrix * wordPos;

    vec2 xy=vec2((clipPosition.x*2.-1.), (clipPosition.y*2.-1.));

    float depth = getDepth(texture2D(depthTexture, clipPosition));

    vec4 viewPosition=czm_inverseProjection*vec4(xy, depth, 1.);

    viewPosition.x = viewPosition.x + .5;
    viewPosition.y = viewPosition.y + .5;

    vec4 worldPosition = czm_inverseView * viewPosition;
    vec4 cameraPosition = camera_view_matrix * worldPosition;

    return cameraPosition;
}
void main(){

    //v_textureCoordinates 左下右上0-1

    vec4 color = texture2D(colorTexture, v_textureCoordinates);

    // 釉色 = 结构二维(颜色纹理, 纹理坐标)
    gl_FragColor = color;
    // 深度 = 获取深度(结构二维(深度纹理, 纹理坐标))
    float depth = getDepth(texture2D(depthTexture, v_textureCoordinates));

    // 视角 = (纹理坐标, 深度)
    vec4 viewPos = toEye(v_textureCoordinates, depth);
    // 世界坐标
    vec4 wordPos = czm_inverseView * viewPos;
    // 虚拟相机中坐标
    vec4 vcPos = camera_view_matrix * wordPos;
    float near = .001 * helsing_viewDistance;
    float dis = length(vcPos.xyz);

    if (dis > near && dis < helsing_viewDistance){
        // 透视投影
        vec4 posInEye = camera_projection_matrix * vcPos;
        // 可视区颜色
        // vec4 helsing_visibleAreaColor=vec4(0.,1.,0.,.5);
        // vec4 helsing_invisibleAreaColor=vec4(1.,0.,0.,.5);
        if (visible(posInEye)){


            //                vec4 shadowPosition = czm_inverseProjection * vec4(v_textureCoordinates, 1.0, 1.0);
            //                shadowPosition /= shadowPosition.w;

            //            vec2 xy2 = vec2((v_textureCoordinates.x * 2.0 - 1.0), (v_textureCoordinates.y * 2.0 - 1.0));
            //            float depth = getDepth(texture2D(depthTexture, v_textureCoordinates));
            //            vec4 shadowPosition = czm_inverseProjection * vec4(xy2, depth, 1.0);

            //            vec4 shadowPosition = viewPos;

            vec4 shadowPosition = camera_projection_matrix * camera_view_matrix * czm_inverseView * toEye(v_textureCoordinates, depth);

            shadowPosition /= shadowPosition.w;

            //            shadowPosition.x /= shadowPosition.w;
            //            shadowPosition.y /= shadowPosition.w;
            //            shadowPosition.z /= shadowPosition.w;

            shadowPosition.x = (shadowPosition.x + 1.)/2.;
            shadowPosition.y = (shadowPosition.y + 1.)/2.;
            shadowPosition.z = (shadowPosition.z + 1.)/2.;


            //            vec4 posInCamera4 = vec4(posInCamera2.xy, posInCamera3.z, posInCamera3.w);


            //            posInCamera2 = posInCamera2 / posInCamera2.w;

            //            posInCamera2.x *= posInCamera2.w;
            //            posInCamera2.y *= posInCamera2.w;
            //            posInCamera2.z *= posInCamera2.w;
            //
            //            posInCamera2 =posInCamera2 / posInCamera2.w;


            //
            //
            //            vec4 wordPos2 = czm_inverseView * posInCamera2;
            //            vec4 vcPos2 = toReal(posInCamera2);
            //            vec4 posInEye2 = camera_projection_matrix * vcPos2;

            //            vec4 shadowPosition = shadowMap_matrix * posInCamera2;


            //            vec4 final = toReal(shadowPosition);
            //
            //            gl_FragColor = vec4(final.xy, 0, 1);
            //            return;



            vec4 videoColor = texture2D(helsing_texture, shadowPosition.xy);

            float distancelimit = 400.0;
            float distanceborder = 100.0;
            float distanceOpacity = 1.0;

            if (dis >= (distancelimit + distanceborder / 2.0)) {
                distanceOpacity = 0.0;
            } else if (dis <= (distancelimit - distanceborder / 2.0)) {
                distanceOpacity = 1.0;
            } else {
                distanceOpacity = (distancelimit + distanceborder / 2.0 - dis) / distanceborder;
            }

            float alpha = distanceOpacity * helsing_alpha * videoColor.a;

            float blacklimit = 0.01;
            float difflimit = 0.5;


            //            gl_FragColor = mix(color, vec4(1., 0., 0., 1.), 1.);
            //            return;

            if (videoColor.x < blacklimit && videoColor.y < blacklimit && videoColor.z < blacklimit) {

                gl_FragColor = color;

                //            } else if (distance(color, videoColor) < difflimit) {
                //
                //                gl_FragColor = color;

            } else {

                gl_FragColor =  mix(color, vec4(videoColor.xyz, 1.), alpha);
            }

            //            float vis = shadow(viewPos);
            //            if (vis > 0.3){


            //            gl_FragColor =  mix(gl_FragColor, vec4(final.xy, 0., 1.0), helsing_alpha * videoColor.a);

            //                gl_FragColor = mix(gl_FragColor, helsing_visibleAreaColor, .5);
            //            } else {

            //                gl_FragColor =  mix(color, vec4(videoColor.xyz, 1.), .5);

            //                gl_FragColor = mix(gl_FragColor, helsing_invisibleAreaColor, .5);
            //            }
        }
    }
}